package simulacao;

// AgenteBot

// Java AgentBot.
// Autor: Alexandre Heideker - alexandre.heideker@ufabc.edu.br
// UFABC Jun/2009
//

import java.io.BufferedReader;
import java.io.FileReader;
import swarm.Globals;
import swarm.Selector;
import swarm.defobj.Zone;

import swarm.defobj.FArgumentsImpl;
import swarm.defobj.FCallImpl;

import swarm.activity.Activity;
import swarm.activity.ActionGroup;
import swarm.activity.ActionGroupImpl;
import swarm.activity.Schedule;
import swarm.activity.ScheduleImpl;
import swarm.activity.FActionForEach;

import swarm.objectbase.Swarm;
import swarm.objectbase.SwarmImpl;
import swarm.objectbase.VarProbe;
import swarm.objectbase.MessageProbe;
import swarm.objectbase.EmptyProbeMapImpl;

import java.util.ArrayList;

import swarm.space.Grid2d;
import swarm.space.Grid2dImpl;


public class BotModelSwarm extends SwarmImpl
{

    //memória coletiva dos robôs
    public static Memoria memoria;

    public int numBots = 2;
    public int worldXSize = 40;
    public int worldYSize = 40;
    private Schedule _modelSchedule;
    private ArrayList _botList;
    public Grid2d _world;
    public Grid2d _memo;

    public void setNumBots (int numBots)
    { 
        if (numBots != -1)
            this.numBots = numBots;
    }

    public ArrayList getBotList ()
    { 
        return _botList;
    }
    public Grid2d getWorld ()
    {
        return _world;
    }
    public static Memoria getMemo ()
    {
        return memoria;
    }
    private FActionForEach _actionForEach;

public BotModelSwarm (Zone aZone)
{
    super (aZone);

    EmptyProbeMapImpl botModelProbeMap = new EmptyProbeMapImpl
     (aZone, getClass ());

    botModelProbeMap.addProbe (probeVariable ("numBots"));
    botModelProbeMap.addProbe (probeVariable ("worldXSize"));
    botModelProbeMap.addProbe (probeVariable ("worldYSize"));
    botModelProbeMap.addProbe (probeMessage ("addBots:"));

    Globals.env.probeLibrary.setProbeMap$For
     (botModelProbeMap, getClass ());

}

public Activity activateIn (Swarm swarmContext)
{
    super.activateIn (swarmContext);
    _modelSchedule.activateIn (this);
    return getActivity ();
}

public Object addBot (int numNewBots)
{
    numBots += numNewBots;
    System.out.println ("Eu vou adicionar " + numNewBots + " novo(s) Robô(s)");
    return this;
}

public Object buildActions ()
{
    super.buildActions();

    ActionGroup modelActions = new ActionGroupImpl (getZone ());

    try
    {
        Bot proto = (Bot) _botList.get (0);
        Selector sel = new Selector (proto.getClass (), "BotStep", false);
        _actionForEach = modelActions.createFActionForEachHomogeneous$call
         (_botList, new FCallImpl (this, proto, sel, new FArgumentsImpl (this, sel)));
    } catch (Exception e)
    {
        e.printStackTrace (System.err);
    }
    _actionForEach.setDefaultOrder (Globals.env.Sequential);

    _modelSchedule = new ScheduleImpl (getZone (), 1);

    _modelSchedule.at$createAction (0, modelActions);

    try {
        _modelSchedule.createActionTo$message
        (this, new Selector (this.getClass (), "modelStep", false));
    } catch (Exception e) {
        System.err.println ("Exception modelStep: " + e.getMessage ());
    }
    return this;
}


public Object buildObjects ()
{
    super.buildObjects();
    _world = new Grid2dImpl (getZone (), worldXSize, worldYSize);
    _memo = new Grid2dImpl (getZone (), worldXSize, worldYSize);
    memoria = new Memoria(getZone(), worldXSize, worldYSize);
    _botList = new ArrayList ();

    int x = 0;
    int y = 0;

    //Carregar o labirinto...
    
    try {
        BufferedReader br=new BufferedReader( new FileReader("Labirinto.csv"));
        String Linha;
        String[] colunas=new String[40];
        int j=0;
        while ((Linha=br.readLine())!=null) {
            if (Linha.length()>0){
                //System.out.println(Linha);
                colunas=Linha.split(";");
                for (int i=0;i<colunas.length;i++){
                    //incluir os objetos gravados no arquivo
                    if (colunas[i].equalsIgnoreCase("4")){
                        //parede
                        Wall w = new Wall(_world, this, 0);
                        w.putAtX$Y(i,j);
                    }
                }
            }
            j++;
        }
        br.close();
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    // Criando Robôs:
    for (int botIndex = 0; botIndex < numBots; botIndex++)
    {
        Bot bot = new Bot(_world, this, botIndex, memoria);
        _botList.add (bot);
        bot.nome=Integer.toString(botIndex);
        bot.colorIndex=1;
        _world.setOverwriteWarnings (false);
        boolean cy=true;
        while (cy){
            int xTemp=(int) Math.floor(Math.random()*_world.getSizeX());
            int yTemp=(int) Math.floor(Math.random()*_world.getSizeY());
            if (_world.getObjectAtX$Y(xTemp, yTemp)==null) {
                cy=false;
                bot.putAtX$Y(xTemp, yTemp);
            }
        }

    }
    return this;
}

public Object modelStep ()
{
    int x = 2; int y = 2;
    return this;
}

private MessageProbe probeMessage (String name)
{
    return Globals.env.probeLibrary.getProbeForMessage$inClass
     (name, BotModelSwarm.this.getClass ());
}

private VarProbe probeVariable (String name)
{
    return Globals.env.probeLibrary.getProbeForVariable$inClass
     (name, BotModelSwarm.this.getClass ());
}

}
